﻿using IOA.MES.Business;
using IOA.MES.ClientApi.Common;
using IOA.MES.ClientApi.Models.Request.WebTool;
using IOA.MES.ClientApi.Models.Response.WebTool;
using IOA.MES.Common;
using IOA.MES.DataAccess.VModel;
using Newtonsoft.Json;
using NLog;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Web.Http;

namespace IOA.MES.ClientApi.Controllers
{
    /// <summary>
    /// 小工具相关接口
    /// </summary>
    public class WebToolController : ApiController
    {
        private Logger logger = LogManager.GetCurrentClassLogger();
        /// <summary>
        /// 获取打包唛头文件
        /// </summary>
        [HttpPost]
        public ResultJson<GetPackMarkResponse> GetPackMark([FromBody] GetPackMarkRequest request)
        {
            var pack = new WorkOrderMgr().GetPack(request.PackNo);
            var labels = new LabelMgr().GetLabelByPack(request.PackNo);
            if (labels == null)
            {
                throw new MultiLanBizException(120051);//唛头模板不存在
            }
            var ivDatas = new WorkOrderMgr().QueryPackIvDatas(request.PackNo);
            var components = new ComponentMgr().QueryPackComponents(request.PackNo);
            return new ResultJson<GetPackMarkResponse>(new GetPackMarkResponse
            {
                PackMark = labels?.Mark ?? string.Empty,
                BorderBarCode = labels?.BorderBarCode ?? string.Empty,
                PackInfo = new PackInfo
                {
                    PackDate = pack.CreateTime.ToString("yyyy-MM-dd"),
                    PackNo = pack.PackNo,
                    OrderNo = pack.OrderNo,
                    NameplateModel = pack.NameplateModel,
                    CurrentLevel = pack.IVCurrentLevel,
                    Color = pack.ComponentColor,
                    Power = pack.IVPowerLevel ?? 0
                },
                Products = pack.Products.Select(_ => new ProductInfo
                {
                    BarCode = _.BarCode?.ToUpper().Trim(),
                    PackNo = request.PackNo,
                    NameplateModel = ivDatas.FirstOrDefault(iv => string.Equals(iv.BarCode, _.BarCode, StringComparison.CurrentCultureIgnoreCase))?.NameplateModel ?? string.Empty,
                    CurrentLevel = ivDatas.FirstOrDefault(iv => string.Equals(iv.BarCode, _.BarCode, StringComparison.CurrentCultureIgnoreCase))?.IVCurrentRange ?? string.Empty,
                    Power = ivDatas.FirstOrDefault(iv => string.Equals(iv.BarCode, _.BarCode, StringComparison.CurrentCultureIgnoreCase))?.IVPowerLevel?.ToString() ?? string.Empty,
                    FF = ivDatas.FirstOrDefault(iv => string.Equals(iv.BarCode, _.BarCode, StringComparison.CurrentCultureIgnoreCase))?.FF?.ToString() ?? string.Empty,
                    Im = ivDatas.FirstOrDefault(iv => string.Equals(iv.BarCode, _.BarCode, StringComparison.CurrentCultureIgnoreCase))?.Im?.ToString() ?? string.Empty,
                    Isc = ivDatas.FirstOrDefault(iv => string.Equals(iv.BarCode, _.BarCode, StringComparison.CurrentCultureIgnoreCase))?.Isc?.ToString() ?? string.Empty,
                    Pm = ivDatas.FirstOrDefault(iv => string.Equals(iv.BarCode, _.BarCode, StringComparison.CurrentCultureIgnoreCase))?.Pmax?.ToString() ?? string.Empty,
                    Temp = ivDatas.FirstOrDefault(iv => string.Equals(iv.BarCode, _.BarCode, StringComparison.CurrentCultureIgnoreCase))?.Temp?.ToString() ?? string.Empty,
                    Vm = ivDatas.FirstOrDefault(iv => string.Equals(iv.BarCode, _.BarCode, StringComparison.CurrentCultureIgnoreCase))?.Vm?.ToString() ?? string.Empty,
                    Voc = ivDatas.FirstOrDefault(iv => string.Equals(iv.BarCode, _.BarCode, StringComparison.CurrentCultureIgnoreCase))?.Voc?.ToString() ?? string.Empty,
                    Time = _.CreateTime.ToString("yyyy/MM/dd HH:mm:ss"),
                    EFF = ivDatas.FirstOrDefault(iv => string.Equals(iv.BarCode, _.BarCode, StringComparison.CurrentCultureIgnoreCase))?.ModEff?.ToString() ?? string.Empty,
                    Block = pack.Products.IndexOf(_) + 1,
                    VerifyCode = components.FirstOrDefault(vf => string.Equals(vf.BarCode, _.BarCode, StringComparison.CurrentCultureIgnoreCase))?.VerifyCode?.ToString() ?? string.Empty
                }).ToList()
            });
        }

        /// <summary>
        /// 获取条码打印任务
        /// </summary>
        [HttpPost]
        public ResultJson<GetPrintTaskResponse> GetPrintTask([FromBody] GetPrintTaskRequest request)
        {
            var codes = new WorkOrderMgr().QueryPrintCodes(request.TaskId);
            if (!codes.Any())
            {
                return new ResultJson<GetPrintTaskResponse>();
            }

            var labels = new LabelMgr().GetLabelByCode(codes.FirstOrDefault().Code);
            if (labels == null || string.IsNullOrWhiteSpace(labels.SerialNum))
            {
                throw new MultiLanBizException(120052);//标签模板不存在
            }
            return new ResultJson<GetPrintTaskResponse>(new GetPrintTaskResponse
            {
                Label = labels.SerialNum,
                PrintItems = codes.Select(_ => new BarCodePrintItem
                {
                    BarCode = _.Code,
                    SubName = "SubName"
                }).ToList()
            });
        }

        /// <summary>
        /// 下载图片
        /// </summary>
        [HttpPost]
        public ResultJson<QueryDownloadImagesResponse> QueryDownloadImages([FromBody] QueryDownloadImagesRequest request)
        {
            request.Codes = (request.Codes ?? new List<string>()).Where(_ => !string.IsNullOrWhiteSpace(_)).Select(_ => _.ToUpper().Trim()).Distinct().ToList();
            var response = new ResultJson<QueryDownloadImagesResponse>(new QueryDownloadImagesResponse());
            if (request.ByType < 0 || request.ByType > 2)
            {
                return response;
            }
            else if (request.Codes == null || !request.Codes.Any())
            {
                return response;
            }
            if (!request.SiteTypes.Any())
            {
                return response;
            }

            var components = new List<VComponent>();
            switch (request.ByType)
            {
                case 0:
                    components.AddRange(new ComponentMgr().QueryComponents(string.Empty, string.Empty, request.Codes));
                    break;
                case 1:
                    components.AddRange(new ComponentMgr().QueryComponents(string.Empty, request.Codes.FirstOrDefault(), new List<string>()));
                    break;
                case 2:
                    components.AddRange(new ComponentMgr().QueryComponents(request.Codes.FirstOrDefault(), string.Empty, new List<string>()));
                    break;
                default:
                    break;
            }
            if (!components.Any())
            {
                return response;
            }

            var ftp = new FtpUtils(Convert.ToString(ConfigurationManager.AppSettings["Ftp"]), Convert.ToString(ConfigurationManager.AppSettings["FtpUserName"]), Convert.ToString(ConfigurationManager.AppSettings["FtpPassword"]));
            foreach (var site in request.SiteTypes)
            {
                var folder = new DownloadItem { IsFolder = true };
                switch (site)
                {
                    case 1:
                        folder.ItemName = "EL1图片";
                        break;
                    case 2:
                        folder.ItemName = "接线盒图片";
                        break;
                    case 3:
                        folder.ItemName = "IV数据";
                        break;
                    case 4:
                        folder.ItemName = "IV图片";
                        break;
                    case 5:
                        folder.ItemName = "EL2图片";
                        break;
                    case 6:
                        folder.ItemName = "绝缘耐压数据";
                        break;
                }

                //下载图片
                if (!new[] { 3, 6 }.Contains(site))
                {
                    foreach (var component in components)
                    {
                        var image = new DownloadItem { IsFolder = false, ItemName = component.BarCode };
                        switch (site)
                        {
                            case 1:
                                image.DownloadUrl = component.EL1Image;
                                break;
                            case 2:
                                image.DownloadUrl = component.BoxImage;
                                break;
                            case 4:
                                image.DownloadUrl = component.IvImage;
                                break;
                            case 5:
                                image.DownloadUrl = component.EL2Image;
                                break;
                        }
                        if (!string.IsNullOrWhiteSpace(image.DownloadUrl))
                        {
                            folder.Children.Add(image);
                        }
                    }
                }
                else if (site == 3)
                {
                    var datas = new ProductViaSiteMgr().QueryIvDatas(components.Select(_ => _.BarCode).ToList());
                    var stream = ComopressIvData(datas);
                    stream.Seek(0, SeekOrigin.Begin);
                    var bytes = new byte[stream.Length];
                    logger.Debug($"IV Data Excel Bytes：{bytes.Length}");

                    stream.Read(bytes, 0, bytes.Length);
                    var fileName = $"/tmpFiles/{DateTime.Now:yyyyMMddHHmmssffff}.xlsx";
                    try
                    {
                        logger.Debug($"Ready To Upload IV Excel：{fileName}");
                        ftp.Upload(bytes, fileName);
                        logger.Debug($"IV Excel Upload Success：{fileName}");
                        folder.Children.Add(new DownloadItem { IsFolder = false, ItemName = "IV数据", DownloadUrl = $"{ConfigurationManager.AppSettings["Ftp"]}{fileName}" });
                    }
                    catch (Exception ex)
                    {
                        logger.Fatal(ex, "IV Excel Upload Failed");
                    }
                }
                else if (site == 6)
                {
                    var datas = new ProductViaSiteMgr().QueryInsulateDatas(components.Select(_ => _.BarCode).ToList());
                    var stream = ComopressInsulateData(datas);
                    stream.Seek(0, SeekOrigin.Begin);
                    var bytes = new byte[stream.Length];
                    logger.Debug($"Insulate Data Excel Bytes：{bytes.Length}");

                    stream.Read(bytes, 0, bytes.Length);
                    var fileName = $"/tmpFiles/{DateTime.Now:yyyyMMddHHmmssffff}.xlsx";
                    try
                    {
                        logger.Debug($"Ready To Upload Insulate Excel：{fileName}");
                        ftp.Upload(bytes, fileName);
                        logger.Debug($"Insulate Excel Upload Success：{fileName}");
                        folder.Children.Add(new DownloadItem { IsFolder = false, ItemName = "绝缘耐压数据", DownloadUrl = $"{ConfigurationManager.AppSettings["Ftp"]}{fileName}" });
                    }
                    catch (Exception ex)
                    {
                        logger.Fatal(ex, "Insulate Excel Upload Failed");
                    }
                }

                response.Data.DownloadItems.Add(folder);
            }

            return response;
        }

        private Stream ComopressIvData(List<VProductViaSiteIVData> datas)
        {
            logger.Debug($"Ready To Compress IV Data：{datas.Count}");
            var book = new XSSFWorkbook();
            var sheet = book.CreateSheet("IV数据");
            var stream = new NpoiMemoryStream();
            stream.AllowClose = false;
            if (!datas.Any())
            {
                book.Write(stream);
                book = null;
                return stream;
            }

            var styleCenter = book.CreateCellStyle();
            styleCenter.Alignment = HorizontalAlignment.Center;
            styleCenter.VerticalAlignment = VerticalAlignment.Center;
            styleCenter.BorderBottom = BorderStyle.Thin;
            styleCenter.BorderLeft = BorderStyle.Thin;
            styleCenter.BorderRight = BorderStyle.Thin;
            styleCenter.BorderTop = BorderStyle.Thin;

            var fstData = JsonConvert.DeserializeObject<List<KeyValuePair<string, string>>>(datas.FirstOrDefault().FullData);
            var row1 = sheet.CreateRow(0);
            row1.Height = 30 * 20;
            row1.CreateCell(0).SetCellValue("序号");
            row1.GetCell(0).CellStyle = styleCenter;
            foreach (var item in fstData)
            {
                var cell = row1.CreateCell(fstData.IndexOf(item) + 1);
                cell.SetCellValue(item.Key);
                cell.CellStyle = styleCenter;
            }

            var ivGroups = datas.GroupBy(_ => _.BarCode);
            var i = 1;
            foreach (var item in ivGroups)
            {
                var tmpRow = sheet.CreateRow(i);
                tmpRow.Height = 30 * 20;
                tmpRow.CreateCell(0).SetCellValue(i);
                tmpRow.GetCell(0).CellStyle = styleCenter;

                var curData = JsonConvert.DeserializeObject<List<KeyValuePair<string, string>>>(item.OrderByDescending(_ => _.PkId).FirstOrDefault().FullData);
                foreach (var data in curData)
                {
                    var cell = tmpRow.CreateCell(curData.IndexOf(data) + 1);
                    cell.SetCellValue(data.Value);
                    cell.CellStyle = styleCenter;
                }
                i++;
            }

            book.Write(stream);
            book = null;
            return stream;
        }

        private Stream ComopressInsulateData(List<VProductViaSiteInsulateData> datas)
        {
            logger.Debug($"Ready To Compress Insulate Data：{datas.Count}");
            var book = new XSSFWorkbook();
            var sheet = book.CreateSheet("绝缘耐压数据");
            var stream = new NpoiMemoryStream();
            stream.AllowClose = false;
            if (!datas.Any())
            {
                book.Write(stream);
                book = null;
                return stream;
            }

            var styleCenter = book.CreateCellStyle();
            styleCenter.Alignment = HorizontalAlignment.Center;
            styleCenter.VerticalAlignment = VerticalAlignment.Center;
            styleCenter.BorderBottom = BorderStyle.Thin;
            styleCenter.BorderLeft = BorderStyle.Thin;
            styleCenter.BorderRight = BorderStyle.Thin;
            styleCenter.BorderTop = BorderStyle.Thin;

            var row1 = sheet.CreateRow(0);
            row1.Height = 30 * 20;
            row1.CreateCell(0).SetCellValue("序号");

            var index = 0;
            var properities = typeof(VProductViaSiteInsulateData).GetProperties()
                .Where(_ => !typeof(BaseVModel).GetProperties().Select(p => p.Name).Contains(_.Name, StringComparer.CurrentCultureIgnoreCase))
                .Where(_ => !new[] { "ViaSiteId" }.Contains(_.Name, StringComparer.CurrentCultureIgnoreCase)).ToList();
            foreach (var properity in properities)
            {
                index++;
                var cell = row1.CreateCell(index);
                cell.SetCellValue(properity.Name);
                cell.CellStyle = styleCenter;
            }

            var rowIndex = 0;
            foreach (var data in datas)
            {
                rowIndex++;
                var tmpRow = sheet.CreateRow(rowIndex);
                tmpRow.Height = 30 * 20;
                tmpRow.CreateCell(0).SetCellValue(rowIndex);
                tmpRow.GetCell(0).CellStyle = styleCenter;

                var colIndex = 0;
                foreach (var properity in properities)
                {
                    colIndex++;
                    var cell = tmpRow.CreateCell(colIndex);
                    cell.SetCellValue(Convert.ToString(properity.GetValue(data)));
                    cell.CellStyle = styleCenter;
                }
            }

            book.Write(stream);
            book = null;
            return stream;
        }
    }
}
